package org.example.coursemangementserver.server.interceptor;

import org.example.coursemangementserver.common.constant.ExceptionMessageConstant;
import org.example.coursemangementserver.common.constant.JwtClaimsConstant;
import org.example.coursemangementserver.common.context.BaseContext;
import org.example.coursemangementserver.common.context.ThreadLocalInfo;
import org.example.coursemangementserver.common.exception.admin.AdminJwtException;
import org.example.coursemangementserver.common.exception.common.NoLoginException;
import org.example.coursemangementserver.common.exception.student.StudentJwtException;
import org.example.coursemangementserver.common.exception.teacher.TeacherJwtException;
import org.example.coursemangementserver.common.properties.JwtProperties;
import org.example.coursemangementserver.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * jwt令牌校验的拦截器
 * @author 12438
 */
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 请求拦截器对拦截后的请求进行处理
     * @param request
     * @param response
     * @param handler
     * @return
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //获取请求的url地址
        String requestUrl = request.getRequestURL().toString();
        //判断该请求是否需要验证令牌
        if (shouldIntercept(requestUrl)) {
            //从请求头中获取令牌
            String token = request.getHeader(jwtProperties.getHeaderTokenName());
            //从配置文件里面获取请求令牌名称
            if (!StringUtils.hasLength(token)) {
                //是否存在令牌
                log.info("请求:{}的请求头token为空，返回未登录异常", requestUrl);
                throw new NoLoginException(ExceptionMessageConstant.NULL_TOKEN);
            }
            //判断发起该请求的用户角色，是老师，学生，还是教务人员
            String role = request.getHeader("role");
            if ("3".equals(role) && requestUrl.contains("/admin")) {
                log.info("拦截到教务人员请求，请求的url为：{}", requestUrl);
                //校验教务人员令牌
                try {
                    log.info("教务人员jwt令牌校验:{}", token);
                    Claims claims = JwtUtil.parseJWT(token, jwtProperties.getMangerSecretKey());
                    String username = String.valueOf(claims.get(JwtClaimsConstant.USERNAME).toString());
                    Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
                    log.info("发出当前教务人员请求的教务人员的username：{}", username);
                    ThreadLocalInfo currentUserInfo = new ThreadLocalInfo(userId,username, 3);
                    BaseContext.setCurrentUser(currentUserInfo);
                    //将发送该请求的用户的id信息放在该线程的单独存储空间上
                    //通过，放行
                    return true;
                } catch (Exception ex) {
                    ex.printStackTrace();
                    //jwt校验不通过，抛出令牌异常
                    throw new AdminJwtException(ExceptionMessageConstant.JWT_PARSE_FAILED);
                }
            } else if ("2".equals(role)&& requestUrl.contains("/teacher")){
                log.info("拦截到老师请求，请求的url为：{}", requestUrl);
                //校验用户令牌
                try {
                    log.info("老师jwt令牌校验:{}", token);
                    Claims claims = JwtUtil.parseJWT(token, jwtProperties.getTeacherSecretKey());
                    String username = String.valueOf(claims.get(JwtClaimsConstant.USERNAME).toString());
                    Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
                    log.info("发出当前老师请求的老师的教工号：{}", username);
                    ThreadLocalInfo currentUserInfo = new ThreadLocalInfo(userId,username, 2);
                    BaseContext.setCurrentUser(currentUserInfo);
                    //将发送该请求的用户的id信息放在该线程的单独存储空间上，以区分不同老师
                    //通过，放行
                    return true;
                } catch (Exception ex) {
                    //jwt校验不通过，抛出令牌异常
                    throw new TeacherJwtException(ExceptionMessageConstant.JWT_PARSE_FAILED);
                }
            } else if ("1".equals(role) && requestUrl.contains("/student")) {
                log.info("拦截到学生请求，请求的url为：{}", requestUrl);
                //校验用户令牌
                try {
                    log.info("学生jwt令牌校验:{}", token);
                    Claims claims = JwtUtil.parseJWT(token, jwtProperties.getStudentSecretKey());
                    String username = String.valueOf(claims.get(JwtClaimsConstant.USERNAME).toString());
                    Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
                    log.info("发出当前学生请求的学生的学号：{}", username);
                    ThreadLocalInfo currentUserInfo = new ThreadLocalInfo(userId,username, 1);
                    BaseContext.setCurrentUser(currentUserInfo);
                    //将发送该请求的用户的id信息放在该线程的单独存储空间上，以区分不同学生
                    //通过，放行
                    return true;
                } catch (Exception ex) {
                    //jwt校验不通过，抛出令牌异常
                    throw new StudentJwtException(ExceptionMessageConstant.JWT_PARSE_FAILED);
                }
            }
        }
        log.info("收到普通请求，路径为:{}", requestUrl);
        return true;
    }

    /**
     * 路径判断方法，判断该路径是否是需要验证令牌
     * @param requestUrl// 请求路径
     * @return //返回是否需要验证令牌
     */
    private boolean shouldIntercept(String requestUrl) {
        if(requestUrl.contains("/user") || requestUrl.contains("/error") || requestUrl.contains("/common")){
            return false;
        }
        return true;
    }
}

